package mark.tom.friend.presenter;

import com.alibaba.android.arouter.facade.annotation.Autowired;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import mark.tom.friend.bean.bo.AppInfoBO;
import mark.tom.friend.bean.db.AppInfoDO;
import mark.tom.friend.bean.db.AppInfoDODao;
import mark.tom.friend.bean.db.DaoSession;
import mark.tom.friend.contract.MainContract;
import mark.tom.friend.provider.ISystemProvider;

import javax.inject.Inject;
import java.util.concurrent.Callable;

public class MainPresenter implements MainContract.Presenter {

    // 选择app请求编码
    public final static int REQUEST_CODE_SELECT_APP = 1001;
    private final static int MAX_APP_HIS_COUNT = 9;
    // view Obj
    private MainContract.View mView;
    // appInfoDao Obj
    private AppInfoDODao appInfoDao;
    // 数据转换器
    private AppInfoBO.AppInfoDOConvert appInfoConvert;

    @Autowired public ISystemProvider systemProvider;

    @Inject MainPresenter(MainContract.View mView, DaoSession mDaoSession) {
        this.mView = mView;
        this.appInfoDao = mDaoSession.getAppInfoDODao();
    }

    @Inject void init() {
        appInfoConvert = new AppInfoBO.AppInfoDOConvert();
    }

    @Override
    public void onStart() {
        mView.refreshListView();
    }

    @Override
    public Observable<AppInfoBO> listAppInfo() {
        // 获取所有应用缓存
        return Observable
                .defer(new Callable<ObservableSource<AppInfoDO>>() {
                    @Override
                    public ObservableSource<AppInfoDO> call() {
                        return Observable.fromIterable(appInfoDao.queryBuilder().orderDesc(AppInfoDODao.Properties.Id).list());
                    }
                })
                .map(new Function<AppInfoDO, AppInfoBO>() {
                    @Override
                    public AppInfoBO apply(@NonNull AppInfoDO appInfoDO) {
                        AppInfoBO appInfoBO = appInfoConvert.convert(appInfoDO);
                        appInfoBO.setIcon(systemProvider.getAppIconByPackageName(appInfoDO.getPackageName()));
                        return appInfoBO;
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    @Override
    public Observable<Long> onResult(int requestCode, Object data) {
        switch (requestCode) {
            case REQUEST_CODE_SELECT_APP: {
                if (null == data || !(data instanceof AppInfoBO)) {
                    return null;
                }
                final AppInfoBO appInfo = (AppInfoBO) data;
                // 保存选中的数据到数据库
                return Observable
                        .defer(new Callable<ObservableSource<AppInfoBO>>() {
                            @Override
                            public ObservableSource<AppInfoBO> call() {
                                return Observable.just(appInfo);
                            }
                        })
                        .doOnNext(new Consumer<AppInfoBO>() {
                            @Override
                            public void accept(@NonNull AppInfoBO appInfoBO) {
                                AppInfoDO appInfoDO = appInfoDao.queryBuilder()
                                        .where(AppInfoDODao.Properties.PackageName.eq(appInfoBO.getPackageName()))
                                        .unique();
                                if (appInfoDO != null) {
                                    appInfoDao.delete(appInfoDO);
                                }
                            }
                        })
                        .doOnNext(new Consumer<AppInfoBO>() {
                            @Override
                            public void accept(@NonNull AppInfoBO appInfoBO) {
                                long count = appInfoDao.count();
                                if (count >= MAX_APP_HIS_COUNT) {
                                    appInfoDao.deleteInTx(appInfoDao.queryBuilder()
                                            .orderAsc(AppInfoDODao.Properties.Id)
                                            .limit((int) (count - (MAX_APP_HIS_COUNT - 1)))
                                            .list());
                                }
                            }
                        })
                        .map(new Function<AppInfoBO, AppInfoDO>() {
                            @Override
                            public AppInfoDO apply(@NonNull AppInfoBO appInfoBO) {
                                AppInfoDO appInfoDO = appInfoConvert.unConvert(appInfoBO);
                                String[] fingerprint = systemProvider.getAppSignatureByPackageName(appInfo.getPackageName());
                                appInfoDO.setMd5Fingerprint(fingerprint[0]);
                                appInfoDO.setSha1Fingerprint(fingerprint[1]);
                                return appInfoDO;
                            }
                        })
                        .map(new Function<AppInfoDO, Long>() {
                            @Override
                            public Long apply(@NonNull AppInfoDO appInfoDO) {
                                return appInfoDao.insert(appInfoDO);
                            }
                        })
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread());
            }
            default: {
                return null;
            }
        }
    }

    @Override
    public void onDestroy() {
        mView = null;
    }
}
